/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.myfaces.extensions.cdi.forge.api;

import org.jboss.forge.project.dependencies.Dependency;
import org.jboss.forge.project.dependencies.DependencyBuilder;
import org.jboss.forge.project.dependencies.DependencyResolver;
import org.jboss.forge.project.facets.BaseFacet;
import org.jboss.forge.project.facets.DependencyFacet;
import org.jboss.forge.shell.ShellMessages;
import org.jboss.forge.shell.ShellPrintWriter;
import org.jboss.forge.shell.ShellPrompt;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Cosmin Martinconi, 24.06.2011
 */
public class CodiFacet extends BaseFacet {

    private static final String CODI_VERSION = "codi.version";

    @Inject
    private ShellPrompt prompt;
    @Inject
    private ShellPrintWriter writer;
    @Inject
    private DependencyResolver resolver;

    public boolean install() {
        DependencyFacet deps = getProject().getFacet(DependencyFacet.class);

        installCodiDependency(deps, CodiModule.CODI_CORE.getDependency());

        ArrayList<CodiModule> codiModules = new ArrayList<CodiModule>(Arrays.asList(CodiModule.values()));
        codiModules.remove(CodiModule.CODI_CORE);

        if (prompt.promptBoolean("Would you like to install a CODI module?")) {
            do {
                CodiModule module = prompt.promptChoiceTyped("Install which CODI module?", codiModules);
                installCodiDependency(deps, module.getDependency());

                codiModules.remove(module);
            } while (prompt.promptBoolean("Would you like to install another CODI module?") && !codiModules.isEmpty());
        }

        return true;
    }

    @SuppressWarnings("unchecked")
    public boolean isInstalled() {
        DependencyFacet deps = getProject().getFacet(DependencyFacet.class);

        return deps.hasDependency(CodiModule.CODI_CORE.getDependency().getApi()) &&
                deps.hasDependency(CodiModule.CODI_CORE.getDependency().getImpl());
    }

    private void installCodiDependency(DependencyFacet deps, CodiDependency dependency) {

        if (dependency.getSubDependencyList() != null) {
            installCodiDependency(deps, prompt.promptChoiceTyped("Install which " + dependency.getDescription() + "?", dependency.getSubDependencyList()));
            return;
        }

        DependencyBuilder api = dependency.getApi();
        DependencyBuilder impl = dependency.getImpl();

        writer.println();

        List<Dependency> apiVersions = resolver.resolveVersions(api);
        Dependency apiVersion = prompt.promptChoiceTyped("Install which version?",
               apiVersions, apiVersions.isEmpty() ? null : apiVersions.get(apiVersions.size() - 1));

        Dependency existing = deps.getDependency(apiVersion);
        if ((existing != null)
                && prompt.promptBoolean("Existing CODI dependency was found. Replace [" + existing + "] with ["
                    + apiVersion + "]?")) {
            deps.removeDependency(existing);
        }

        if (deps.getProperty(CODI_VERSION)==null) {
            deps.setProperty(CODI_VERSION, apiVersion.getVersion());
            ShellMessages.info(writer, "'" + CODI_VERSION + "' build dependency property added");
        }

        if (deps.getProperty(CODI_VERSION).equals(apiVersion.getVersion())) {
            api.setVersion("${" + CODI_VERSION + "}");
            if (impl != null) {
                impl.setVersion("${" + CODI_VERSION + "}");
            }
        } else {
            api.setVersion(apiVersion.getVersion());
            if (impl != null) {
                impl.setVersion(apiVersion.getVersion());
            }
        }

        deps.addDependency(api);
        if (impl != null) {
            deps.addDependency(impl);
        }
        ShellMessages.info(writer, "'" + dependency + "' added to dependencies list");
    }


}
